/**
 * 
 */
package org.stars.daostars.sqlmapper.loader.xml;

/**
 * @author Francesco Benincasa (908099)
 * 
 */
import java.io.File;
import java.io.FilenameFilter;
import java.io.InputStream;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.stars.daostars.core.Profile;
import org.stars.daostars.core.DaoStars;
import org.stars.util.StringUtility;

/**
 * Classe loader per la definizione delle query per i vari Dao. Le definizioni
 * vengono messe in una variabile <code>DaoSql</code>.
 * <p>
 * 
 * @author Francesco Benincasa (908099)
 * @since 1.0.0, 14/08/2006
 * 
 */
public class DaoLoader {

	public Log getLog() {
		return LogFactory.getLog(getClass());
	}

	/**
	 * instanza parser xml
	 */
	private SAXParser				parser;

	/**
	 * connessione di default
	 */
	private String				defaultConnectionName;



	/**
	 * Costruttore. Inizializza il logger.
	 * 
	 * @param profile
	 *            profilo sul quale inserire le definizioni di dao
	 * @throws SAXException 
	 * @throws ParserConfigurationException 
	 */
	public DaoLoader(Profile profile) throws ParserConfigurationException, SAXException {
		currentProfile = profile;
		parser = SAXParserFactory.newInstance().newSAXParser();
		handler=new DaoLoaderHandler();
	}
	
	Profile currentProfile;
	
	DaoLoaderHandler handler;

	/**
	 * @param sDirName
	 * @return <code>true</code> se riesce a caricare tutti il file
	 *         <code>.xml</code>
	 */
	public int loadFromDirectory(String sDirName) {
		Log log = getLog();

		File dir = new File(sDirName);

		// This filter only returns file
		FilenameFilter filenameFilter = new FilenameFilter() {
			@Override
			public boolean accept(File file, String name) {
				String sFilename = file + (String.valueOf(File.separatorChar)) + name;
				return (new File(sFilename)).isFile() && name.endsWith(".xml");
			}
		};

		String[] children = dir.list(filenameFilter);

		log.info("Lettura dei dao nella directory " + sDirName);

		if (children == null || children.length == 0) {
			log.error("Nella cartella " + sDirName + " non e' stata trovata alcuna definizione di dao. Sei sicuro che la cartella esista?");
			return 0; // non abbiamo elementi da caricare
		}

		int c = 0;
		for (String filename : children) {
			c++;
			// Get filename of file or directory
			loadFile(sDirName, filename);
			log.debug("Analizzato file " + filename);
		}

		log.debug("Analizzate " + c + " definizioni di dao nella cartella " + sDirName);
		return DaoStars.getInstance().size();
	}

	/**
	 * Carica il file xml presente nella cartella
	 * 
	 * @param sDirName
	 * @param sFileName
	 * @return <code>true</code> se riesce a caricare il file di definizione
	 */
	public boolean loadFile(String sDirName, String sFileName) {
		boolean bRet = false;
		Log log = getLog();
		try {
			String currentFileName = StringUtility.replace(sFileName, ".xml", "").toUpperCase();

			File file=new File(sDirName + "/" + sFileName);
			parser.parse(file, handler.setFileName(currentFileName).setCurrentProfile(currentProfile));			
			currentProfile.addDao(handler.getDaoDefinition());

			bRet = true;
		} catch (Exception e) {
			log.error("Impossibile caricare il file " + sFileName + "\n[" + e.toString() + "]");
		}
		return bRet;
	}

	/**
	 * Carica il file a partire da un inputStream
	 * 
	 * @param sFileName
	 *            filename da caricare
	 * @param inputStream
	 *            inputStream
	 * @return <code>true</code> se non ci sono stati problemi.
	 */
	public boolean loadFromInputStream(String sFileName, InputStream inputStream) {
		boolean bRet = false;
		Log log = getLog();
		try {
			int b = sFileName.lastIndexOf("/");

			if (b > 0) {
				sFileName = sFileName.substring(b + 1);
			}
			String currentFileName = StringUtility.replace(sFileName, ".xml", "").toUpperCase();
			
			parser.parse(new InputSource(inputStream), handler.setFileName(currentFileName).setCurrentProfile(currentProfile));
			currentProfile.addDao(handler.getDaoDefinition());
			
			bRet = true;
		} catch (Exception e) {
			log.error("Impossibile caricare il file " + sFileName + "\n[" + e.toString() + "]");
		}
		return bRet;
	}



	/*
	 * Implementa il metodo dell'interfaccia DaoLoader. Questa implementazione
	 * prende come parametro in ingresso la directory dove sono collocate le
	 * varie definizioni.
	 * 
	 * @see it.insiel.daostars.core.DaoLoader#load(java.lang.String)
	 */
	public int load(String params) {
		return loadFromDirectory(params);
	}

	/**
	 * Getter dell'attributo defaultConnectionName.
	 * 
	 * @return the defaultConnectionName
	 */
	public String getDefaultConnectionName() {
		return defaultConnectionName;
	}

	/**
	 * Setter dell'attributo defaultConnectionName.
	 * 
	 * @param defaultConnectionName
	 *            the defaultConnectionName to set
	 */
	public void setDefaultConnectionName(String defaultConnectionName) {
		this.defaultConnectionName = defaultConnectionName;
	}


}
